/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package extension.room.analyse;

import java.util.LinkedList;
import java.util.List;
import log.Debug;

/**
 *
 * @author daz
 */
public class CardSet {

    public static final int NOT_COMPLETE = 0;
    public static final int FLUSH = 1;
    public static final int PAIR = 2;
    public static final int FLUSH_MISS = 3;
    public static final int PAIR_MISS = 4;
    public static final int THREE_PAIR = 5;
    private List<Integer> listCards;
    private List<Integer> listEatCards;
    private int type;
    public boolean isRemove;
    public boolean isContainEatCard;
    public int numberDuplicate;

    public CardSet(int[] cardId, int type) {
        this.type = type;
        listCards = new LinkedList<Integer>();
        listEatCards = new LinkedList<Integer>();
        for (int i = 0; i < cardId.length; i++) {
            listCards.add(cardId[i]);
        }
    }

    public CardSet(List<Integer> listCardInit, int type) {
        this.type = type;
        listCards = new LinkedList<Integer>();
        listEatCards = new LinkedList<Integer>();
        for (Integer card : listCardInit) {
            listCards.add(card);
        }
    }

    public CardSet(int type) {
        this.type = type;
        listCards = new LinkedList<Integer>();
    }

    public void addCard(int cardId) {
        listCards.add(cardId);
    }

    public void removeCard(int cardId) {
        for (int i = 0; i < listCards.size(); i++) {
            if (cardId == listCards.get(i)) {
                listCards.remove(i);
                break;
            }
        }
    }

    public void removeAllCard(int cardId) {
        for (int i = 0; i < listCards.size(); i++) {
            if (cardId == listCards.get(i)) {
                listCards.remove(i);
            }
        }
    }

    public String getTypeName() {
        switch (type) {
            case PAIR:
                return "PAIR";
            default:
                return "FLUSH";
        }
    }

    public List<Integer> getListCards() {
        return listCards;
    }

    @Override
    public String toString() {
        StringBuilder setBuilder = new StringBuilder();
        for (Integer i : listCards) {
            setBuilder.append(",").append(Card.getRank(i)).append(Card.getSuit(i));
        }
        return setBuilder.toString();
    }

    public boolean contain(int cardFight) {
        for (Integer card : listCards) {
            if (card == cardFight) {
                return true;
            }
        }
        return false;
    }

    public List<Integer> getNearCard(int cardFight) {
        List<Integer> nearCard = new LinkedList<Integer>();
        int listCardSize = listCards.size();
        for (int i = 0; i < listCardSize; i++) {
            if (listCards.get(i).equals(cardFight)) {
                if (i == 0) {
                    nearCard.add(listCards.get(i + 1));
                    nearCard.add(listCards.get(i + 2));
                } else if (i == listCardSize - 1) {
                    nearCard.add(listCards.get(i - 1));
                    nearCard.add(listCards.get(i - 2));
                } else {
                    nearCard.add(listCards.get(i + 1));
                    nearCard.add(listCards.get(i - 1));
                }
            }
        }
        nearCard.add(cardFight);
        return nearCard;
    }

    public boolean contain(List<Integer> listCardCheck) {
        if (listCardCheck.isEmpty()) {
            return false;
        }
        for (Integer cardCheck : listCardCheck) {
            for (Integer card : listCards) {
                if (cardCheck.equals(card)) {
                    return true;
                }
            }
        }
        return false;
    }

    public int sumPoint() {
        int sum = 0;
        for (Integer card : listCards) {
            sum += (card % 13);
        }
        return sum;
    }

    public int duplicateChange(CardSet set2) {
//        Debug.d("list card1:" + listCards.toString());
//        Debug.d("list card2:" + set2.getListCards().toString());
        for (Integer card1 : listCards) {
            for (Integer card2 : set2.getListCards()) {
                if (card1.equals(card2)) {
                    if (checkCanRemove(card1)) {
                        removeCard(card1);
                        return -1;
                    }
                    if (set2.checkCanRemove(card2)) {
                        set2.removeCard(card2);
                        return -1;
                    }

                    return card1;
                }
            }
        }
        return -1;
    }

    public int duplicateNotChange(CardSet set2) {
        for (Integer card1 : listCards) {
            for (Integer card2 : set2.getListCards()) {
                if (card1.equals(card2)) {
                    return card1;
                }
            }
        }
        return -1;
    }

    public boolean checkCanReplace(Integer newCard, Integer oldCard) {
        int[] temp = new int[listCards.size()];
        int count = 0;
        for (Integer cardId : listCards) {
            if (!oldCard.equals(cardId)) {
                temp[count] = cardId;
                count++;
            }
        }
        temp[count] = newCard;
        if (type == PAIR) {
            return checkPair(temp, count);
        }
        return checkFlush(temp, count);

    }

    public boolean checkCanRemove(Integer cardCheck) {
//        Debug.d("remove set :" + listCards.toString() + ",card :" + cardCheck);
        int[] temp = new int[listCards.size() - 1];
        int count = 0;
        for (Integer cardId : listCards) {
            if (!cardCheck.equals(cardId)) {
                temp[count] = cardId;
                count++;
            }
        }

        if (type == PAIR) {
            return checkPair(temp, count);
        }
        return checkFlush(temp, count);
    }

    public int getSetSize() {
        return listCards.size();
    }

    public boolean checkCanRemove(List<Integer> listCheck) {
        int[] temp = new int[listCards.size()];
        int count = 0;
        for (Integer cardId : listCards) {
            boolean isDuplicate = false;
            for (Integer cardCheck : listCheck) {
                if (cardCheck.equals(cardId)) {
                    isDuplicate = true;
                    break;
                }

            }
            if (!isDuplicate) {
                temp[count] = cardId;
                count++;
            }
        }

        int[] tempCheck = new int[count];
        System.arraycopy(temp, 0, tempCheck, 0, count);
        if (type == PAIR) {
            return checkPair(tempCheck, count - 1);
        }
        return checkFlush(tempCheck, count - 1);
    }

    public void resetListEat() {
        listEatCards.clear();
    }

    public void addEatCard(Integer card) {
        listEatCards.add(card);
    }

    public List<Integer> getListEatCards() {
        return listEatCards;
    }

    public boolean checkCanRemoveEatCard() {
//        Debug.d("remove set :" + listCards.toString() + ",card :" + cardCheck);
        int[] temp1 = new int[listCards.size() - 1];
        int count = 0;
        for (Integer cardId : listCards) {
            boolean isDuplicate = false;
            for (Integer cardCheck : listEatCards) {
                if (cardCheck.equals(cardId)) {
                    isDuplicate = true;
                    break;

                }
            }
            if (!isDuplicate) {
                temp1[count] = cardId;
                count++;
            }
        }
        int[] temp2 = new int[count];
        System.arraycopy(temp1, 0, temp2, 0, count);
        if (type == PAIR) {
            return checkPair(temp2, count);
        }
        return checkFlush(temp2, count);
    }

    private boolean checkFlush(int[] listCards, int setSize) {
        int numberCards = listCards.length;
        for (int i = 0; i < numberCards; i++) {
            for (int j = i + 1; j < numberCards; j++) {
                if (listCards[i] / 13 > listCards[j] / 13
                        || (listCards[i] / 13 == listCards[j] / 13
                        && listCards[i] % 13 > listCards[j] % 13)) {
                    swap(i, j, listCards);
                }
            }
        }
        for (int i = 0; i < numberCards; i++) {
            int step = 0;
            int cardId = listCards[i];
            for (int j = i + 1; j < numberCards; j++) {
                if (cardId + (j - i) == listCards[j] && cardId / 13 == listCards[j] / 13) {
                    step++;
                } else {
                    j = numberCards;
                }
            }
            if (step != 0) {
//                int[] flsush = new int[step + 1];
//                for (int k = i; k <= i + step; k++) {
//                    flsush[k - i] = listCards[k];
////                    Debug.n(Card.getRank(listCards[k]) + Card.getSuit(listCards[k]));
//
//                }
                if (step >= setSize - 1 && step >= 2) {
                    return true;
                }
                i = i + step;
            }
        }
        return false;
    }

    private static void swap(int i, int j, int[] listCards) {
        int temp = listCards[j];
        listCards[j] = listCards[i];
        listCards[i] = temp;
    }

    private boolean checkPair(int[] listCards, int setSize) {
        int numberCards = listCards.length;
        for (int i = 0; i < numberCards; i++) {
            for (int j = i + 1; j < numberCards; j++) {
                if (listCards[i] % 13 > listCards[j] % 13) {
                    int temp = listCards[j];
                    listCards[j] = listCards[i];
                    listCards[i] = temp;
                }
            }
        }

        for (int i = 0; i < numberCards; i++) {
            int cardId = listCards[i];
            int step = 0;
            for (int j = i + 1; j < numberCards; j++) {
                if (cardId % 13 == listCards[j] % 13) {
                    if (j < numberCards - 1 && cardId % 13 == listCards[j + 1] % 13) {
                        if (j < numberCards - 2 && cardId % 13 == listCards[j + 2] % 13) {
                            step = 3;
                        } else {
                            step = 2;
                        }
                    } else {
                        step = 1;
                    }
//                    int[] pair = new int[step + 1];
//                    for (int k = i; k <= i + step; k++) {
//                        pair[k - i] = listCards[k];
//                    }
                    if (step >= setSize - 1 && step >= 2) {
                        return true;
                    }
                    j = numberCards;
                    i = i + step;
                }
            }
        }
        return false;
    }

    public int getType() {
        return type;
    }

    public boolean canAddToSet(int cardAdd) {
        int[] temp = new int[listCards.size() + 1];
        int count = 0;
//        Debug.d("check :" + listCards.toString());
        for (Integer cardId : listCards) {
            temp[count] = cardId;
            count++;
        }
        temp[count] = cardAdd;
        if (type == PAIR) {
            return checkPair(temp, count + 1);
        } else {
            return checkFlush(temp, count + 1);
        }
    }

    public void moreDuplicate() {
        this.numberDuplicate++;
    }

    public int getNumberDuplicate() {
        return numberDuplicate;
    }

    public void setNumberDuplicate(int numberDuplicate) {
        this.numberDuplicate = numberDuplicate;
    }

    public CardSet extractSetAfterRemove(int duplicate) {
        int[] temp = new int[listCards.size() - 1];
        int count = 0;
        for (Integer cardId : listCards) {
            if (!cardId.equals(duplicate)) {
                temp[count] = cardId;
                count++;
            }
        }
        for (int i = 0; i < count; i++) {
            int step = 0;
            int cardId = temp[i];
            for (int j = i + 1; j < count; j++) {
                if (cardId + (j - i) == temp[j] && cardId / 13 == temp[j] / 13) {
                    step++;
                } else {
                    j = count;
                }
            }
            if (step != 0) {
                int[] flush = new int[step + 1];
                for (int k = i; k <= i + step; k++) {
                    flush[k - i] = temp[k];
                }
                if (step >= 2) {
                    return new CardSet(flush, CardSet.FLUSH);
                }
                i = i + step;
            }
        }
        return null;
    }

    public CardSet extractSetAfterRemove(List<Integer> duplicate) {
        int[] temp = new int[listCards.size() - 1];
        int count = 0;
        for (Integer cardId : listCards) {
            boolean isDuplicate = false;
            for (Integer cardDuplicate : duplicate) {
                if (cardId.equals(cardDuplicate)) {
                    isDuplicate = true;
                    break;
                }
            }
            if (!isDuplicate) {
                temp[count] = cardId;
                count++;
            }
        }
        for (int i = 0; i < count; i++) {
            int step = 0;
            int cardId = temp[i];
            for (int j = i + 1; j < count; j++) {
                if (cardId + (j - i) == temp[j] && cardId / 13 == temp[j] / 13) {
                    step++;
                } else {
                    j = count;
                }
            }
            if (step != 0) {
                int[] flush = new int[step + 1];
                for (int k = i; k <= i + step; k++) {
                    flush[k - i] = temp[k];
                }
                if (step >= 2) {
                    return new CardSet(flush, CardSet.FLUSH);
                }
                i = i + step;
            }
        }
        return null;
    }

    public void removeEatCard() {
        for (Integer remove : listEatCards) {
            for (Integer card : listCards) {
                if (remove.equals(card)) {
                    listCards.remove(card);
                    break;
                }
            }
        }
    }

    public int getSuit() {
        return listCards.get(0) / 13;
    }

    public int getRankMin() {
        return (listCards.get(0) - 2 + 13) % 13;
    }

    public int getRankMax() {
        return (listCards.get(listCards.size() - 1) - 2 + 13) % 13;
    }

    private int getCardRank(int cardId) {
        return (cardId - 2 + 13) % 13;
    }

    public boolean isBiggerSpecial(CardSet currentSet) {
        if (getRankMax() > currentSet.getRankMax()) {
            return true;
        } else if (getRankMax() == currentSet.getRankMax()) {
            int setSize = currentSet.getSetSize();
            if (listCards.get(setSize - 1) / 13 < currentSet.getCardId(setSize - 1) / 13) {
                return true;
            }
        }
        return false;

    }

    public boolean isBigger(CardSet currentSet) {
        if (type == PAIR) {
            return getRankMax() > currentSet.getRankMax();
        } else {
            return getRankMin() > currentSet.getRankMax();
        }
    }

    public boolean checkTwoPair() {
        int sum = (listCards.get(0) / 13 + listCards.get(1) / 13);
        if (sum == 1 || sum == 5) {
            return true;
        }
        return false;
    }

    public boolean checkSetSpecail() {
        for (Integer card : listCards) {
            if (card % 13 != 1) {
                return false;
            }
        }
        return true;
    }

    public boolean checkSameSet(CardSet currentSet) {
        Debug.d("check same set ");
        Debug.d("list card :" + listCards.toString());
        Debug.d("current set :" + currentSet.toString());
        int setSize = listCards.size();
        for (int i = 0; i < setSize; i++) {
            if (listCards.get(i) / 13 != currentSet.getCardId(i) / 13) {
                Debug.d("not same set");
                return false;
            }
        }
        return true;
    }

    public int getCardId(int id) {
        return listCards.get(id);
    }
}
